home *** CD-ROM | disk | FTP | other *** search
- /*
- * Definitions and declarations used throughout the run-time system.
- * These are also used by the linker in constructing data for use by
- * the run-time system.
- */
-
- #ifdef StandardC
- #include <time.h>
- #endif /* StandardC */
- #include "..\h\cpuconf.h"
- #include "..\h\memsize.h"
-
- /*
- * Constants that are not likely to vary between implementations.
- */
-
- #define BitOffMask (IntBits-1)
- #define CsetSize (256/IntBits) /* number of ints to hold 256 cset
- * bits. Use (256/IntBits)+1 if
- * 256 % IntBits != 0 */
- #define MinListSlots 8 /* number of elements in an expansion
- * list element block */
-
- #define MaxCvtLen 257 /* largest string in conversions; the extra
- * one is for a terminating null */
- #define MaxReadStr 512 /* largest string to read() in one piece */
- #define MaxIn 32767 /* largest number of bytes to read() at once */
- #define RandA 1103515245 /* random seed multiplier */
- #define RandC 453816694 /* random seed additive constant */
- #define RanScale 4.65661286e-10 /* random scale factor = 1/(2^31-1)) */
-
- /*
- * File status flags in status field of file blocks.
- */
- #define Fs_Read 01 /* read access */
- #define Fs_Write 02 /* write access */
- #define Fs_Create 04 /* file created on open */
- #define Fs_Append 010 /* append mode */
- #define Fs_Pipe 020 /* reading/writing on a pipe */
-
- #ifdef RecordIO
- #define Fs_Record 040 /* record structured file */
- #endif /* RecordIO */
-
- #ifdef StandardLib
- #define Fs_Reading 0100 /* last file operation was read */
- #define Fs_Writing 0200 /* last file operation was write */
- #endif /* StandardLib */
-
- /*
- * Definitions for interpreter actions.
- */
- #define A_Failure 1 /* routine failed */
- #define A_Suspension 2 /* routine suspended */
- #define A_Return 3 /* routine returned */
- #define A_Pret_uw 4 /* interp unwind for Op_Pret */
- #define A_Unmark_uw 5 /* interp unwind for Op_Unmark */
- #define A_Resumption 6 /* resume generator */
- #define A_Pfail_uw 7 /* interp unwind for Op_Pfail */
- #define A_Lsusp_uw 8 /* interp unwind for Op_Lsusp */
- #define A_Eret_uw 9 /* interp unwind for Op_Eret */
- #define A_Coact 10 /* co-expression activated */
- #define A_Coret 11 /* co-expression returned */
- #define A_Cofail 12 /* co-expression failed */
-
- /*
- * Codes returned by invoke to indicate action.
- */
- #define I_Builtin 201 /* A built-in routine is to be invoked */
- #define I_Fail 202 /* goal-directed evaluation failed */
- #define I_Continue 203 /* Continue execution in the interp loop */
- #define I_Vararg 204 /* A function with a variable number of args */
-
- /*
- * Codes returned by runtime support routines.
- * Note, some conversion routines also return type codes. Other routines may
- * return positive values other than return codes. sort() places restrictions
- * on Less, Equal, and Greater.
- */
- #define Less -1
- #define Equal 0
- #define Greater 1
- #define CvtFail -2
- #define Cvt -3
- #define NoCvt -4
- #define Failure -5
- #define Defaulted -6
- #define Success -7
- #define Error -8
-
- /*
- * Generator types.
- */
- #define G_Csusp 1
- #define G_Esusp 2
- #define G_Psusp 3
-
- /*
- * Type codes (descriptors and blocks).
- */
- #define T_Null 0 /* null value */
- #define T_Integer 1 /* integer */
-
- #ifdef LargeInts
- #define T_Bignum 2 /* long integer */
- #endif /* LargeInts */
-
- #define T_Real 3 /* real number */
- #define T_Cset 4 /* cset */
- #define T_File 5 /* file */
- #define T_Proc 6 /* procedure */
- #define T_List 7 /* list header */
- #define T_Table 8 /* table header */
- #define T_Record 9 /* record */
- #define T_Telem 10 /* table element */
- #define T_Lelem 11 /* list element */
- #define T_Tvsubs 12 /* substring trapped variable */
- #define T_Tvkywd 13 /* keyword trapped variable */
- #define T_Tvtbl 14 /* table element trapped variable */
- #define T_Set 15 /* set header */
- #define T_Selem 16 /* set element */
- #define T_Refresh 17 /* refresh block */
- #define T_Coexpr 18 /* co-expression */
- #define T_External 19 /* external block */
- #define T_Slots 20 /* set/table hash slots */
-
- #define MaxType 20 /* maximum type number */
-
- /*
- * Descriptor types and flags.
- */
-
- #define D_Null (word)(T_Null | F_Nqual)
- #define D_Integer (word)(T_Integer | F_Nqual)
-
- #ifdef LargeInts
- #define D_Bignum (word)(T_Bignum | F_Ptr | F_Nqual)
- #endif /* LargeInts */
-
- #define D_Real (word)(T_Real | F_Ptr | F_Nqual)
- #define D_Cset (word)(T_Cset | F_Ptr | F_Nqual)
- #define D_File (word)(T_File | F_Ptr | F_Nqual)
- #define D_Proc (word)(T_Proc | F_Ptr | F_Nqual)
- #define D_List (word)(T_List | F_Ptr | F_Nqual)
- #define D_Table (word)(T_Table | F_Ptr | F_Nqual)
- #define D_Telem (word)(T_Telem | F_Ptr | F_Nqual)
- #define D_Tvsubs (word)(T_Tvsubs | D_Tvar)
- #define D_Tvkywd (word)(T_Tvkywd | D_Tvar)
- #define D_Tvtbl (word)(T_Tvtbl | D_Tvar)
- #define D_Record (word)(T_Record | F_Ptr | F_Nqual)
- #define D_Set (word)(T_Set | F_Ptr | F_Nqual)
- #define D_Refresh (word)(T_Refresh | F_Ptr | F_Nqual)
- #define D_Coexpr (word)(T_Coexpr | F_Ptr | F_Nqual)
- #define D_External (word)(T_External | F_Ptr | F_Nqual)
- #define D_Slots (word)(T_Slots | F_Ptr | F_Nqual)
-
- #define D_Var (word)(F_Var | F_Nqual | F_Ptr)
- #define D_Tvar (word)(D_Var | F_Tvar)
-
- #define TypeMask 63 /* type mask */
- #define OffsetMask (~(D_Tvar)) /* offset mask for variables */
-
- /*
- * Run-time data structures.
- */
-
- /*
- * Icode consists of operators and arguments. Operators are small integers,
- * while arguments may be pointers. To conserve space in icode files on
- * computers with 16-bit ints, icode is written by the linker as a mixture
- * of ints and words (longs). When an icode file is read in and processed
- * by the interpreter, it looks like a C array of mixed ints and words.
- * Accessing this "nonstandard" structure is handled by a union of int and
- * word pointers and incrementing is done by incrementing the appropriate
- * member of the union (see the interpreter). This is a rather dubious
- * method and certainly not portable. A better way might be to address
- * icode with a char *, but the incrementing code might be inefficient
- * (at a place that experiences a lot of execution activity).
- *
- * For the moment, the dubious coding is isolated under control of the
- * size of integers.
- */
-
- #if IntBits == 16
-
- typedef union {
- int *op;
- word *opnd;
- } inst;
-
- #else /* IntBits == 16 */
-
- typedef union {
- word *op;
- word *opnd;
- } inst;
-
- #endif /* IntBits == 16 */
-
- /*
- * Descriptor
- */
-
- struct descrip { /* descriptor */
- word dword; /* type field */
- union {
- word integr; /* integer value */
- char *sptr; /* pointer to character string */
- union block *bptr; /* pointer to a block */
- dptr descptr; /* pointer to a descriptor */
- } vword;
- };
-
- struct sdescrip {
- word length; /* length of string */
- char *string; /* pointer to string */
- };
-
- /*
- * Run-time error numbers and text.
- */
- struct errtab {
- int err_no; /* error number */
- char *errmsg; /* error message */
- };
-
- /*
- * Frame markers
- */
- struct ef_marker { /* expression frame marker */
- inst ef_failure; /* failure ipc */
- struct ef_marker *ef_efp; /* efp */
- struct gf_marker *ef_gfp; /* gfp */
- word ef_ilevel; /* ilevel */
- };
-
- struct pf_marker { /* procedure frame marker */
- word pf_nargs; /* number of arguments */
- struct pf_marker *pf_pfp; /* saved pfp */
- struct ef_marker *pf_efp; /* saved efp */
- struct gf_marker *pf_gfp; /* saved gfp */
- dptr pf_argp; /* saved argp */
- inst pf_ipc; /* saved ipc */
- word pf_ilevel; /* saved ilevel */
- dptr pf_scan; /* saved scanning environment */
- struct descrip pf_locals[1]; /* descriptors for locals */
- };
-
- struct gf_marker { /* generator frame marker */
- word gf_gentype; /* type */
- struct ef_marker *gf_efp; /* efp */
- struct gf_marker *gf_gfp; /* gfp */
- inst gf_ipc; /* ipc */
- struct pf_marker *gf_pfp; /* pfp */
- dptr gf_argp; /* argp */
- };
-
- /*
- * Generator frame marker dummy -- used only for sizing "small"
- * generator frames where procedure infomation need not be saved.
- * The first five members here *must* be identical to those for
- * gf_marker.
- */
- struct gf_smallmarker { /* generator frame marker */
- word gf_gentype; /* type */
- struct ef_marker *gf_efp; /* efp */
- struct gf_marker *gf_gfp; /* gfp */
- inst gf_ipc; /* ipc */
- };
-
- #ifdef LargeInts
-
- typedef unsigned int DIGIT;
-
- struct b_bignum { /* large integer block */
- word title; /* T_Bignum */
- word blksize; /* block size */
- word msd, lsd; /* most and least significant digits */
- int sign; /* sign; 0 positive, 1 negative */
- DIGIT digits[1]; /* digits */
- };
-
- #endif /* LargeInts */
- struct b_real { /* real block */
- word title; /* T_Real */
- double realval; /* value */
- };
-
- struct b_cset { /* cset block */
- word title; /* T_Cset */
- word size; /* size of cset */
- int bits[CsetSize]; /* array of bits */
- };
-
- struct b_file { /* file block */
- word title; /* T_File */
- FILE *fd; /* Unix file descriptor */
- word status; /* file status */
- struct descrip fname; /* file name (string qualifier) */
- };
-
- struct b_proc { /* procedure block */
- word title; /* T_Proc */
- word blksize; /* size of block */
- union { /* entry points for */
- int (*ccode)(); /* C routines */
- uword ioff; /* and icode as offset */
- pointer icode; /* and icode as absolute pointer */
- } entryp;
- word nparam; /* number of parameters */
- word ndynam; /* number of dynamic locals */
- word nstatic; /* number of static locals */
- word fstatic; /* index (in global table) of first static */
- struct descrip pname; /* procedure name (string qualifier) */
- struct descrip lnames[1]; /* list of local names (qualifiers) */
- };
-
- /*
- * b_iproc blocks are used to statically initialize information about
- * functions. They are identical to b_proc blocks except for
- * the pname field which is a sdecrip (simple/string descriptor) instead
- * of a descrip. This is done because unions cannot be initialized.
- */
-
- struct b_iproc { /* procedure block */
- word ip_title; /* T_Proc */
- word ip_blksize; /* size of block */
- int (*ip_entryp)(); /* entry point (code) */
- word ip_nparam; /* number of parameters */
- word ip_ndynam; /* number of dynamic locals */
- word ip_nstatic; /* number of static locals */
- word ip_fstatic; /* index (in global table) of first static */
- struct sdescrip ip_pname; /* procedure name (string qualifier) */
- struct descrip ip_lnames[1]; /* list of local names (qualifiers) */
- };
-
- struct b_list { /* list-header block */
- word title; /* T_List */
- word size; /* current list size */
- word id; /* identification number */
- union block *listhead; /* pointer to first list-element block */
- union block *listtail; /* pointer to last list-element block */
- };
-
- struct b_lelem { /* list-element block */
- word title; /* T_Lelem */
- word blksize; /* size of block */
- union block *listprev; /* previous list-element block */
- union block *listnext; /* next list-element block */
- word nslots; /* total number of slots */
- word first; /* index of first used slot */
- word nused; /* number of used slots */
- struct descrip lslots[1]; /* array of slots */
- };
-
- struct b_slots { /* set/table hash slots */
- word title; /* T_Slots */
- word blksize; /* size of block */
- union block *hslots[HSlots]; /* array of slots (HSlots * 2^n entries) */
- };
-
- struct b_table { /* table-header block */
- word title; /* T_Table */
- word size; /* current table size */
- word id; /* identification number */
- word mask; /* mask to get slot num, equals n slots - 1 */
- struct b_slots *hdir[HSegs]; /* directory of hash slot segments */
- struct descrip defvalue; /* default table element value */
- };
-
- struct b_telem { /* table-element block */
- word title; /* T_Telem */
- union block *clink; /* hash chain link */
- uword hashnum; /* for ordering chain */
- struct descrip tref; /* entry value */
- struct descrip tval; /* assigned value */
- };
-
- /*
- * A set header must be a proper prefix of a table header,
- * and a set element must be a proper prefix of a table element.
- */
- struct b_set { /* set-header block */
- word title; /* T_Set */
- word size; /* size of the set */
- word id; /* identification number */
- word mask; /* mask to get slot num, equals n slots - 1 */
- struct b_slots *hdir[HSegs]; /* directory of hash slot segments */
- };
-
- struct b_selem { /* set-element block */
- word title; /* T_Selem */
- union block *clink; /* hash chain link */
- uword hashnum; /* hash number */
- struct descrip setmem; /* the element */
- };
-
- struct b_record { /* record block */
- word title; /* T_Record */
- word blksize; /* size of block */
- word id; /* identification number */
- union block *recdesc; /* pointer to record constructor */
- struct descrip fields[1]; /* fields */
- };
-
- /*
- * Alternate uses for procedure block fields, applied to records.
- */
- #define nfields nparam /* number of fields */
- #define recnum nstatic /* record number */
- #define recid fstatic /* record serial number */
- #define recname pname /* record name */
-
- struct b_tvkywd { /* keyword trapped variable block */
- word title; /* T_Tvkywd */
- int (*putval)(); /* assignment function for keyword */
- struct descrip kyval; /* keyword value */
- struct descrip kyname; /* keyword name */
- };
-
- struct b_tvsubs { /* substring trapped variable block */
- word title; /* T_Tvsubs */
- word sslen; /* length of substring */
- word sspos; /* position of substring */
- struct descrip ssvar; /* variable that substring is from */
- };
-
- struct b_tvtbl { /* table element trapped variable block */
- word title; /* T_Tvtbl */
- union block *clink; /* pointer to table header block */
- uword hashnum; /* hash number */
- struct descrip tref; /* entry value */
- struct descrip tval; /* reserved for assigned value */
- };
-
- struct b_coexpr { /* co-expression stack block */
- word title; /* T_Coexpr */
- word size; /* number of results produced */
- word id; /* identification number */
- struct b_coexpr *nextstk; /* pointer to next allocated stack */
- struct pf_marker *es_pfp; /* current pfp */
- struct ef_marker *es_efp; /* efp */
- struct gf_marker *es_gfp; /* gfp */
- dptr es_argp; /* argp */
- inst es_ipc; /* ipc */
- word es_ilevel; /* interpreter level */
- word *es_sp; /* sp */
- dptr tvalloc; /* where to place transmitted value */
- struct descrip freshblk; /* refresh block pointer */
- struct astkblk *es_actstk; /* pointer to activation stack structure */
- word cstate[CStateSize]; /* C state information */
- };
-
- struct astkblk { /* co-expression activator-stack block */
- int nactivators; /* number of valid activator entries in
- * this block */
- struct astkblk *astk_nxt; /* next activator block */
- struct actrec { /* activator record */
- word acount; /* number of calls by this activator */
- struct b_coexpr *activator; /* the activator itself */
- } arec[ActStkBlkEnts];
- };
-
- struct b_refresh { /* co-expression block */
- word title; /* T_Refresh */
- word blksize; /* size of block */
- word *ep; /* entry point */
- word numlocals; /* number of locals */
- struct pf_marker pfmkr; /* marker for enclosing procedure */
- struct descrip elems[1]; /* arguments and locals, including Arg0 */
- };
-
- struct b_external { /* external block */
- word title; /* T_External */
- word blksize; /* size of block */
- word descoff; /* offset to first descriptor */
- word exdata[1]; /* words of external data */
- };
-
- union block { /* general block */
-
- #ifdef LargeInts
- struct b_bignum bignumblk;
- #endif /* LargeInts */
-
- struct b_real realblk;
- struct b_cset cset;
- struct b_file file;
- struct b_proc proc;
- struct b_list list;
- struct b_lelem lelem;
- struct b_table table;
- struct b_telem telem;
- struct b_set set;
- struct b_selem selem;
- struct b_record record;
- struct b_tvkywd tvkywd;
- struct b_tvsubs tvsubs;
- struct b_tvtbl tvtbl;
- struct b_refresh refresh;
- struct b_coexpr coexpr;
- struct b_external externl;
- struct b_slots slots;
- };
-
- /*
- * Declarations for entries in tables associating icode location with
- * source program location.
- */
- struct ipc_fname {
- word ipc; /* offset of instruction into code region */
- word fname; /* offset of file name into string region */
- };
-
- struct ipc_line {
- word ipc; /* offset of instruction into code region */
- int line; /* line number */
- };
-
- /*
- * External declarations.
- */
-
- extern char *code; /* start of icode */
-
- extern word stksize; /* size of co-expression stacks in words */
- extern word *stackend; /* end of evaluation stack */
- extern struct b_coexpr *stklist;/* base of co-expression stack list */
-
- extern word mstksize; /* size of main stack in words */
-
- extern char *statbase; /* start of static space */
- extern char *statend; /* end of static space */
- extern char *statfree; /* static space free list header */
- extern word statsize; /* size of static space */
- extern word statincr; /* size of increment for static space */
-
- extern word ssize; /* size of string space (bytes) */
- extern char *strbase; /* start of string space */
- extern char *strend; /* end of string space */
- extern char *strfree; /* string space free pointer */
-
- extern word abrsize; /* size of allocated block region (words) */
- extern char *blkbase; /* base of allocated block region */
- extern char *blkend; /* maximum address in allocated block region */
- extern char *blkfree; /* first free location in allocated block region */
-
- extern int bsizes[]; /* sizes of blocks */
- extern int firstd[]; /* offset (words) of first descrip. */
- extern char *blkname[]; /* print names for block types. */
- extern uword segsize[]; /* size of hash bucket segment */
-
-
- extern struct b_tvkywd tvky_err; /* trapped variable for &error */
- extern struct b_tvkywd tvky_pos; /* trapped variable for &pos */
- extern struct b_tvkywd tvky_ran; /* trapped variable for &random */
- extern struct b_tvkywd tvky_sub; /* trapped variable for &subject */
- extern struct b_tvkywd tvky_trc; /* trapped variable for &trace */
-
-
- #define k_error tvky_err.kyval.vword.integr /* value of &error */
- #define k_pos tvky_pos.kyval.vword.integr /* value of &pos */
- #define k_random tvky_ran.kyval.vword.integr /* value of &random */
- #define k_subject tvky_sub.kyval /* value of &subject */
- #define k_trace tvky_trc.kyval.vword.integr /* value of &trace */
-
- extern struct b_cset k_ascii; /* value of &ascii */
- extern struct b_cset k_cset; /* value of &cset */
- extern struct b_cset k_digits; /* value of &lcase */
- extern struct b_file k_errout; /* value of &errout */
- extern struct b_file k_input; /* value of &input */
- extern struct b_cset k_lcase; /* value of &lcase */
- extern struct b_cset k_letters; /* value of &letters */
- extern int k_level; /* value of &level */
- extern char *k_errortext; /* value of &errortext */
- extern int k_errornumber; /* value of &errornumber */
- extern struct descrip k_errorvalue; /* value of &errorvalue */
- extern struct descrip k_main; /* value of &main */
- extern struct descrip k_current; /* ¤t */
- extern struct b_file k_output; /* value of &output */
- extern struct b_cset k_ucase; /* value of &ucase */
-
- #ifdef StandardLib
- extern clock_t starttime; /* start time in milliseconds */
- #else /* StandardLib */
- extern long starttime; /* start time in milliseconds */
- #endif /* StandardLib */
-
- extern struct descrip nulldesc; /* null value */
- extern struct descrip zerodesc; /* zero */
- extern struct descrip onedesc; /* one */
- extern struct descrip emptystr; /* empty string */
- extern struct descrip blank; /* blank */
- extern struct descrip letr; /* letter "r" */
- extern struct descrip maps2; /* second argument to map() */
- extern struct descrip maps3; /* third argument to map() */
- extern struct descrip input; /* &input */
- extern struct descrip errout; /* &errout */
- extern struct descrip lcase; /* lowercase string */
- extern struct descrip ucase; /* uppercase string */
-
- extern int ntended; /* number of active tended descriptors */
- extern struct descrip tended[]; /* tended descriptors */
-
- extern word *sp; /* interpreter stack pointer */
- extern word *stack; /* interpreter stack base */
- extern struct pf_marker *pfp; /* procedure frame pointer */
- extern struct ef_marker *efp; /* expression frame pointer */
- extern struct gf_marker *gfp; /* generator frame pointer */
- extern inst ipc; /* interpreter program counter */
- extern dptr argp; /* argument pointer */
- extern int ilevel; /* interpreter level */
-
- #ifdef ExecImages
- extern int dumped; /* the interpreter has been dumped */
- #endif /* ExecImages */
-
- #if EBCDIC == 2
- extern char ToEBCDIC[], FromEBCDIC[]; /* ASCII<->EBCDIC maps */
- #define ToAscii(e) (FromEBCDIC[e])
- #define FromAscii(e) (ToEBCDIC[e])
- #else /* EBCDIC == 2 */
- #define ToAscii(e) (e)
- #define FromAscii(e) (e)
- #endif /* EBCDIC == 2 */
-
-
- /*
- * Evaluation stack overflow margin
- */
-
- #define PerilDelta 100
-
- /*
- * Macro definitions related to descriptors.
- */
-
- /*
- * The following code is operating-system dependent [@rt.01]. Define
- * PushAval for computers that store longs and pointers differently.
- */
-
- #if PORT
- #define PushAVal(x) PushVal(x)
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS
- #define PushAVal(x) PushVal(x)
- #endif /* AMIGA || ATARI_ST || HIGHC_386 ... */
-
- #if MSDOS || OS2
- static union {
- pointer stkadr;
- word stkint;
- } stkword;
-
- #define PushAVal(x) {sp++; \
- stkword.stkadr = (char *)(x); \
- *sp = stkword.stkint;}
- #endif /* MSDOS || OS2 */
-
- /*
- * End of operating-system specific code.
- */
-
- /*
- * Pointer to block.
- */
- #define BlkLoc(d) ((d).vword.bptr)
-
- /*
- * Check for null-valued descriptor.
- */
- #define ChkNull(d) ((d).dword==D_Null)
-
- /*
- * Dereference descriptor.
- */
- #define DeRef(d) (Var(d) ? deref(&d) : Success)
-
- /*
- * Check for equivalent descriptors.
- */
- #define EqlDesc(d1,d2) ((d1).dword == (d2).dword && BlkLoc(d1) == BlkLoc(d2))
-
- /*
- * Integer value.
- */
- #define IntVal(d) ((d).vword.integr)
-
- /*
- * Offset from top of block to value of variable.
- */
- #define Offset(d) ((d).dword & OffsetMask)
-
- /*
- * Check for pointer.
- */
- #define Pointer(d) ((d).dword & F_Ptr)
-
- /*
- * Check for qualifier.
- */
- #define Qual(d) (!((d).dword & F_Nqual))
-
- /*
- * Length of string.
- */
- #define StrLen(q) ((q).dword)
-
- /*
- * Location of first character of string.
- */
- #define StrLoc(q) ((q).vword.sptr)
-
- /*
- * Check for trapped variable.
- */
- #define Tvar(d) ((d).dword & F_Tvar)
-
- /*
- * Location of trapped-variable block.
- */
- #define TvarLoc(d) ((d).vword.bptr)
-
- /*
- * Type of descriptor.
- */
- #define Type(d) (int)((d).dword & TypeMask)
-
- /*
- * Check for variable.
- */
- #define Var(d) ((d).dword & F_Var)
-
- /*
- * Location of the value of a variable.
- */
- #define VarLoc(d) ((d).vword.descptr)
-
- /*
- * Important note: The code that follows is not strictly legal C.
- * It tests to see if pointer p2 is between p1 and p3. This may
- * involve the comparison of pointers in different arrays, which
- * is not well-defined. The casts of these pointers to unsigned "words"
- * (longs or ints, depending) works with all C compilers and architectures
- * on which Icon has been implemented. However, it is possible it will
- * not work on some system. If it doesn't, there may be a "false
- * positive" test, which is likely to cause a memory violation or a
- * loop. It is not practical to implement Icon on a system on which this
- * happens.
- */
-
- #define InRange(p1,p2,p3) ((uword)(p2) >= (uword)(p1) && (uword)(p2) < (uword)(p3))
-
- /*
- * Macros for pushing values on the interpreter stack.
- */
-
- /*
- * Push descriptor.
- */
- #define PushDesc(d) {*++sp = ((d).dword); sp++;*sp =((d).vword.integr);}
-
- /*
- * Push null-valued descriptor.
- */
- #define PushNull {*++sp = D_Null; sp++; *sp = 0;}
-
- /*
- * Push word.
- */
- #define PushVal(v) {*++sp = (word)(v);}
-
- /*
- * Macros related to function and operator definition.
- */
-
- /*
- * Procedure block for a function.
- */
-
- #define FncBlock(f,nargs,deref) \
- struct b_iproc Cat(B,f) = {\
- T_Proc,\
- Vsizeof(struct b_proc),\
- Cat(X,f),\
- nargs,\
- -1,\
- deref, 0,\
- {sizeof(Lit(f))-1,Lit(f)}};
-
-
- /*
- * Function declaration for variable number of arguments.
- */
- #define FncDcl(nm,n) FncBlock(nm,n,0) Cat(X,nm)(cargp) register dptr cargp;
-
- /*
- * Function declaration for variable number of arguments.
- */
- #define FncDclV(nm) FncBlock(nm,-1,0) Cat(X,nm)(nargs,cargp) register dptr cargp;
-
- /*
- * Function declaration without dereferenced arguments.
- */
- #define FncNDcl(nm,n) FncBlock(nm,n,-1) Cat(X,nm)(cargp) register dptr cargp;
-
- /*
- * Function declaration for variable number of arguments.
- */
- #define FncNDclV(nm) FncBlock(nm,-1,-1) Cat(X,nm)(nargs,cargp) register dptr cargp;
-
- /*
- * Declaration for library routine.
- */
- #define LibDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(nargs,cargp) \
- register dptr cargp;
- /*
- * Procedure block for an operator.
- */
- #define OpBlock(f,nargs,sname,realargs)\
- struct b_iproc Cat(B,f) = {\
- T_Proc,\
- Vsizeof(struct b_proc),\
- Cat(O,f),\
- nargs,\
- -1,\
- realargs,\
- 0,\
- {sizeof(sname)-1,sname}};
-
- /*
- * Operator declaration.
- */
- #define OpDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(cargp) register dptr cargp;
-
- /*
- * Agent routine declaration.
- */
- #define AgtDcl(nm) Cat(A,nm)(cargp) register dptr cargp;
-
- #ifdef StrInvoke
- /*
- * Structure for mapping string names of procedures to block addresses.
- */
- struct pstrnm {
- char *pstrep;
- struct b_proc *pblock;
- };
-
- #endif /* StrInvoke */
- /*
- * Character translations.
- */
- #if EBCDIC == 2
- extern char ToEBCDIC[], FromEBCDIC[]; /* ASCII<->EBCDIC maps */
- #define ToAscii(e) (FromEBCDIC[e])
- #define FromAscii(e) (ToEBCDIC[e])
- #else /* EBCDIC == 2 */
- #define ToAscii(e) (e)
- #define FromAscii(e) (e)
- #endif /* EBCDIC == 2 */
-
- /*
- * Macros to access Icon arguments in C functions.
- */
-
- /*
- * n-th argument.
- */
- #define Arg(n) (cargp[n])
-
- /*
- * Type field of n-th argument.
- */
- #define ArgType(n) (cargp[n].dword)
-
- /*
- * Value field of n-th argument.
- */
- #define ArgVal(n) (cargp[n].vword.integr)
-
- /*
- * Specific arguments.
- */
- #define Arg0 (cargp[0])
- #define Arg1 (cargp[1])
- #define Arg2 (cargp[2])
- #define Arg3 (cargp[3])
- #define Arg4 (cargp[4])
- #define Arg5 (cargp[5])
- #define Arg6 (cargp[6])
-
- /*
- * Code expansions for exits from C code for top-level routines.
- */
- #define Fail return A_Failure
- #define Return return A_Return
-
- #define Suspend { \
- int rc; \
- if ((rc = interp(G_Csusp,cargp)) != A_Resumption) \
- return rc;}
-
- #define Forward(agent) return Cat(A,agent)(cargp)
-
- /*
- * Miscellaneous macro definitions.
- */
-
- /*
- * Error exit from non top-level routines.
- */
- #define RetError(n,v) {\
- k_errornumber = n;\
- k_errortext = "";\
- k_errorvalue = v;\
- return Error;}
-
- /*
- * Get floating-point number from real block.
- */
- #ifdef Double
- #define GetReal(dp,res) { \
- word *rp, *rq; \
- rp = (word *) &(res); \
- rq = (word *) &(BlkLoc(*dp)->realblk.realval); \
- *rp++ = *rq++; \
- *rp = *rq;}
- #else /* Double */
- #define GetReal(dp,res) res = BlkLoc(*dp)->realblk.realval
- #endif /* Double */
-
- /*
- * Absolute value of x (word).
- */
- #if SASC
- #define Abs(x) __builtin_abs(x)
- #else /* SASC */
- #define Abs(x) (((x) < 0) ? (-(x)) : (x))
- #endif /* SASC */
-
- /*
- * Maximum of x and y.
- */
- #define Max(x,y) ((x)>(y)?(x):(y))
- #if SASC
- #undef Max
- #define Max(x,y) __builtin_max(x,y)
- #endif /* SASC */
-
- /*
- * Minimum of x and y.
- */
- #define Min(x,y) ((x)<(y)?(x):(y))
- #if SASC
- #undef Min
- #define Min(x,y) __builtin_min(x,y)
- #endif /* SASC */
-
- /*
- * Some C compilers take '\n' and '\r' to be the same, so the
- * following definitions are used.
- */
- #if EBCDIC
- /*
- * Note that, in EBCDIC, "line feed" and "new line" are distinct
- * characters. Icon's use of "line feed" is really "new line" in
- * C terms.
- */
- #define LineFeed '\n' /* if really "line feed", that's 37 */
- #define CarriageReturn '\r'
- #else /* EBCDIC */
- #define LineFeed 10
- #define CarriageReturn 13
- #endif /* EBCDIC */
-
- /*
- * Construct an integer descriptor.
- */
- #define MakeInt(i,dp) { \
- (dp)->dword = D_Integer; \
- IntVal(*dp) = (word)(i);}
-
- /*
- * Check whether a set or table needs resizing.
- */
- #define SP(p) ((struct b_set *)p)
- #define TooCrowded(p) \
- ((SP(p)->size > MaxHLoad*(SP(p)->mask+1)) && (SP(p)->hdir[HSegs-1] == NULL))
- #define TooSparse(p) \
- ((SP(p)->hdir[1] != NULL) && (SP(p)->size < MinHLoad*(SP(p)->mask+1)))
-
- /*
- * RunErr encapsulates a call to the function runerr, followed
- * by Fail. The idea is to avoid the problem of calling
- * runerr directly and forgetting that it may actually return.
- */
-
- #define RunErr(n,dp) {\
- runerr((int)n,dp);\
- Fail;\
- }
-
- /*
- * Vsizeof is for use with variable-sized (i.e., indefinite)
- * structures containing an array of descriptors declared of size 1
- * to avoid compiler warnings associated with 0-sized arrays.
- */
-
- #define Vsizeof(s) (sizeof(s) - sizeof(struct descrip))
-
- /*
- * Offset in word of cset bit.
- */
- #define CsetOff(b) ((b) & BitOffMask)
- /*
- * Address of word of cset bit.
- */
- #define CsetPtr(b,c) ((c) + (((b)&0377) >> LogIntBits))
- /*
- * Set bit b in cset c.
- */
- #define Setb(b,c) (*CsetPtr(b,c) |= (01 << CsetOff(b)))
- /*
- * Test bit b in cset c.
- */
- #define Testb(b,c) ((*CsetPtr(b,c) >> CsetOff(b)) & 01)
-
- /*
- * Handy sizeof macros:
- *
- * Wsizeof(x) -- Size of x in words.
- * Vwsizeof(x) -- Size of x in words, minus the size of a descriptor. Used
- * when structures have a potentially null list of descriptors
- * at their end.
- */
- #define Wsizeof(x) ((sizeof(x) + sizeof(word) - 1) / sizeof(word))
- #define Vwsizeof(x) ((sizeof(x) - sizeof(struct descrip) +sizeof(word) - 1)\
- / sizeof(word))
- /*
- * Definitions and declarations used for storage management.
- */
-
- #define F_Mark 0100000 /* bit for marking blocks */
-
- #define Static 1 /* collection is for static region */
- #define Strings 2 /* collection is for strings */
- #define Blocks 3 /* collection is for blocks */
-
- /*
- * External definitions.
- */
-
- extern char *currend; /* current end of memory region */
- extern uword blkneed; /* stated need for block space */
- extern uword strneed; /* stated need for string space */
- extern uword statneed;
- extern dptr globals; /* start of global variables */
- extern dptr eglobals; /* end of global variables */
- extern dptr gnames; /* start of global variable names */
- extern dptr egnames; /* end of global variable names */
- extern dptr statics; /* start of static variables */
- extern dptr estatics; /* end of static variables */
-
- extern dptr *quallist; /* start of qualifier list */
- extern word qualsize;
-
- /*
- * Get type of block pointed at by x.
- */
- #define BlkType(x) (*(word *)x)
-
- /*
- * BlkSize(x) takes the block pointed to by x and if the size of
- * the block as indicated by bsizes[] is nonzero it returns the
- * indicated size; otherwise it returns the second word in the
- * block contains the size.
- */
- #define BlkSize(x) (bsizes[*(word *)x & ~F_Mark] ? \
- bsizes[*(word *)x & ~F_Mark] : *((word *)x + 1))
-
- /*
- * If memory monitoring is not enabled, redefine function calls
- * to do nothing.
- */
- #ifndef MemMon
- #define MMAlc(n,t)
- #define MMBGC(r)
- #define MMEGC()
- #define MMMark(b,t)
- #define MMShow(d,s)
- #define MMStat(a,l,c)
- #define MMStr(n)
- #define MMSMark(a,n)
- #endif /* MemMon */
-
- #ifndef FixedRegions
-
- /*
- * Information used with Icon's allocation routines with expandable-regions
- * memory management.
- */
-
- typedef int ALIGN; /* pick most stringent type for alignment */
-
- union bhead { /* header of free block */
- struct {
- union bhead *ptr; /* pointer to next free block */
- uword bsize; /* free block size */
- } s;
- ALIGN x; /* force block alignment */
- };
-
- typedef union bhead HEADER;
- #define NALLOC 64 /* units to request at one time */
-
- #define FREEMAGIC 0x807F /* magic flag for free blocks (MemMon only) */
-
- #endif /* FixedRegions */
-